package com.pubinfo.passbook.common.service.mss.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.pubinfo.passbook.common.config.ApplicationConfig;
import com.pubinfo.passbook.common.entity.TContractInvoiceHeader;
import com.pubinfo.passbook.common.entity.TContractWriteoffHeader;
import com.pubinfo.passbook.common.entity.TContractWriteoffItems;
import com.pubinfo.passbook.common.entity.TContractWriteoffRelation;
import com.pubinfo.passbook.common.enums.ContractWriteOffTypeEnum;
import com.pubinfo.passbook.common.exception.ServiceException;
import com.pubinfo.passbook.common.model.bo.witeoff.ContractWiteoffBase;
import com.pubinfo.passbook.common.model.bo.witeoff.subitem.ContractWriteoffItems;
import com.pubinfo.passbook.common.model.dto.witeoff.CompensateForRemoveDTO;
import com.pubinfo.passbook.common.model.http.baseEntity.BaseBody;
import com.pubinfo.passbook.common.model.http.baseEntity.Baseinfo;
import com.pubinfo.passbook.common.model.http.baseEntity.Message;
import com.pubinfo.passbook.common.model.http.baseEntity.request.IRequest;
import com.pubinfo.passbook.common.model.http.baseEntity.request.RequestEnvelope;
import com.pubinfo.passbook.common.model.http.request.AutoCreateWriteoff.AutoCreateWriteoffBody;
import com.pubinfo.passbook.common.model.http.request.AutoCreateWriteoff.ContractAutoCreateWriteoffMessageList;
import com.pubinfo.passbook.common.model.http.response.GetAutoCreateWriteoff.WriteoffEnvelope;
import com.pubinfo.passbook.common.model.http.response.GetAutoCreateWriteoff.WriteoffMessage;
import com.pubinfo.passbook.common.model.vo.base.BusinessErrorCode;
import com.pubinfo.passbook.common.model.vo.base.JsonResult;
import com.pubinfo.passbook.common.service.contract.TContractInvoiceHeaderService;
import com.pubinfo.passbook.common.service.contract.TContractWriteoffHeaderService;
import com.pubinfo.passbook.common.service.contract.TContractWriteoffItemsService;
import com.pubinfo.passbook.common.service.contract.TContractWriteoffRelationService;
import com.pubinfo.passbook.common.service.mss.CompensateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Date;

@Slf4j
@Service
public class CompensateServiceImpl implements CompensateService {

    @Resource
    ApplicationConfig config;
    @Resource
    private TContractWriteoffHeaderService contractWriteoffHeaderService;
    @Resource
    private TContractWriteoffItemsService contractWriteoffItemsService;
    @Resource
    private TContractWriteoffRelationService contractWriteoffRelationService;
    @Resource
    private TContractInvoiceHeaderService contractInvoiceHeaderService;

    @Override
    public JsonResult<String> compensateForRemove(CompensateForRemoveDTO jobDTO, Boolean isCheckPermission) {
        //设置结转报账单具体信息
//      if (jobDTO.getWriteoffType() == ContractWriteOffTypeEnum.carry_over.getType()) {
//        jobDTO.setEconomicItemCode("100601");//经济事项编码
//        jobDTO.setEconomicItemName("非经营性业务");//经济事项名称
//      } else if (jobDTO.getWriteoffType() == ContractWriteOffTypeEnum.TAXES_DRAW.getType()) {
//        jobDTO.setEconomicItemCode("10060301");//经济事项编码
//        jobDTO.setEconomicItemName("税费计提");//经济事项名称
//      }
//      jobDTO.setSapCompayCode("B011");//公司代码
//      jobDTO.setAccountCode("G933000009");//会计科目编码
//        jobDTO.setAccountName("赔补类供应商");//会计科目名称
//        jobDTO.setAccountType("1");//会计科目类型 选输(1-总账、2-供应商、3-客户),有科目时必须
//        jobDTO.setPickingMode("0");//业务场景
        jobDTO.setHappenDate(DateUtil.format(new Date(), "yyyy-MM-dd"));//费用发生日期
        jobDTO.setBudgetSet(DateUtil.format(new Date(), "yyyy-MM"));//费用发生期间
        //设置子单金额之合等于总单金额
//        BigDecimal sum = new BigDecimal(0);
//        for (ContractWriteoffItems lineItem : jobDTO.getLineItems()) {
//            sum = sum.add(lineItem.getSum());
//        }
//        jobDTO.setSum(sum);
        //设置外围系统组单Id
        String otherSystemMainId = IdWorker.getIdStr();
        jobDTO.setOtherSystemMainId(otherSystemMainId);
        for (ContractWriteoffItems lineItem : jobDTO.getLineItems()) {
            lineItem.setOtherSystemDetailId(otherSystemMainId);
        }
        return postXmlAndSave(jobDTO, JSONObject.parseObject(JSON.toJSONString(jobDTO)));
    }


    private JsonResult<String> postXmlAndSave(ContractWiteoffBase witeoffBase, JSONObject jsonObject) {
        String postUrl = config.getEsb().getUrl() + config.getEsb().getApi().getGainWriteoffInstStatus();
        BaseBody baseBody = new BaseBody();
        Message message = new Message(new ContractAutoCreateWriteoffMessageList(witeoffBase));
        baseBody.setBaseinfo(Baseinfo.createBaseinfo("AutoCreateWriteoff", new Date()));
        baseBody.setMessage(message);
        RequestEnvelope requestEnvelope = new RequestEnvelope();
        AutoCreateWriteoffBody body = new AutoCreateWriteoffBody();
        IRequest IRequest = new IRequest();
        IRequest.setBaseBody(baseBody);
        body.setIRequest(IRequest);
        requestEnvelope.setRequestBody(body);
        //发送post请求
        String s = null;
        WriteoffEnvelope writeoffEnvelope = null;
        try {
            log.info(new XmlMapper().writeValueAsString(requestEnvelope));
            s = sendPost(new XmlMapper().writeValueAsString(requestEnvelope), postUrl);
            writeoffEnvelope = new XmlMapper().readValue(s, WriteoffEnvelope.class);
        } catch (UnirestException | IOException e) {
            throw new ServiceException("报账请求失败", e);
        }
        s = s.replaceAll("&#60;", "<").replaceAll("&#62;", ">");

        log.info(writeoffEnvelope.getBody().getEResponse().getBaseBody().getMessage().getMessage());

        WriteoffMessage writeoffMessage = null;
        try {
            String thisMessage = writeoffEnvelope.getBody().getEResponse().getBaseBody()
                    .getMessage().getMessage().replaceAll("<!\\[CDATA\\[", "")
                    .replaceAll("\\]\\]>", "");
            writeoffMessage = new XmlMapper().readValue(thisMessage, WriteoffMessage.class);
        } catch (IOException e) {
            throw new ServiceException("报账失败", e);
        }
        if (writeoffMessage.getTYPE().equals("S")) {
            try {
                saveInstance(witeoffBase, new XmlMapper().writeValueAsString(requestEnvelope), jsonObject);
            } catch (JsonProcessingException e) {
                throw new ServiceException("报账失败", e);
            }
        } else {
            log.error("合同结转失败：{}", writeoffMessage.getItems().get(0).getErrorMsg());
            throw new ServiceException(BusinessErrorCode.COMPENSATE_REMOVE_ERROR);

        }
        return JsonResult.success("成功");
    }

    private void saveInstance(ContractWiteoffBase witeoffBase, String xml, JSONObject json) {
        TContractWriteoffHeader contractWriteoffHeader = new TContractWriteoffHeader(witeoffBase, xml, json);
        //contractWriteoffHeader.getStatus();
        //保存数据到报账单表
        contractWriteoffHeaderService.save(contractWriteoffHeader);
        Integer writeiffId = contractWriteoffHeader.getWriteoffId();
        //保存报账子单信息集合
        for (ContractWriteoffItems lineItem : witeoffBase.getLineItems()) {
            lineItem.setWriteoffId(writeiffId);
            contractWriteoffItemsService.save(new TContractWriteoffItems(lineItem));
        }
        //保存报账单关联收入及项目成本信息
        for (TContractWriteoffRelation witeoff : witeoffBase.getWriteOffInfo()) {
            witeoff.setWriteoffId(writeiffId);
            contractWriteoffRelationService.save(witeoff);
        }
        //税金计提成功后修改发票状态
        if (witeoffBase.getWriteoffType() == ContractWriteOffTypeEnum.TAXES_DRAW.getType()){
            UpdateWrapper<TContractInvoiceHeader> updateWrapper = new UpdateWrapper<>();
            for (Integer contractId : witeoffBase.getContractIds()) {
                updateWrapper.eq("contract_id", contractId);
                updateWrapper.set("status",1);
                contractInvoiceHeaderService.update(null,updateWrapper);
            }
        }
    }

    private String sendPost(String xml, String url) throws UnirestException {
        Unirest.setTimeouts(0, 0);
        HttpResponse<String> response = Unirest.post(url)
                .header("Authorization", config.getEsb().getAuthorization())
                .header("User-Agent", "apifox/1.0.0")
                .header("Content-Type", "application/xml").body(xml)
                .asString();
        return response.getBody();
    }


}
